package ${projectDomain}.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import ${projectDomain}.adapter.system.SystemDepartmentAdapter;
import ${projectDomain}.adapter.system.SystemDepartmentJobAdapter;
import ${projectDomain}.adapter.system.SystemDepartmentJobUserAdapter;
import ${projectDomain}.adapter.system.SystemJobAdapter;
import ${projectDomain}.annotation.logger.OperatorLogger;
import ${projectDomain}.enums.OperatorTypeEnum;
import ${projectDomain}.enums.tree.TreeIconEnum;
import ${projectDomain}.pojo.bo.system.department.SystemDepartmentCreateBo;
import ${projectDomain}.pojo.bo.system.department.SystemDepartmentDeleteBo;
import ${projectDomain}.pojo.bo.system.department.SystemDepartmentPageBo;
import ${projectDomain}.pojo.bo.system.department.SystemDepartmentTreeBo;
import ${projectDomain}.pojo.bo.system.department.SystemDepartmentUpdateBo;
import ${projectDomain}.pojo.bo.system.department.SystemDepartmentViewBo;
import ${projectDomain}.pojo.dao.sql.Sql;
import ${projectDomain}.pojo.dao.system.department.SystemDepartmentDataDo;
import ${projectDomain}.pojo.dao.system.department.SystemDepartmentDeleteDo;
import ${projectDomain}.pojo.dao.system.department.SystemDepartmentInsertDo;
import ${projectDomain}.pojo.dao.system.department.SystemDepartmentPageDo;
import ${projectDomain}.pojo.dao.system.department.SystemDepartmentSearchDo;
import ${projectDomain}.pojo.dao.system.department.SystemDepartmentSingleDo;
import ${projectDomain}.pojo.dao.system.department.SystemDepartmentUpdateDo;
import ${projectDomain}.pojo.dao.system.department.job.SystemDepartmentJobDeleteBatchDo;
import ${projectDomain}.pojo.dao.system.department.job.SystemDepartmentJobInsertBatchDo;
import ${projectDomain}.pojo.dao.system.department.job.SystemDepartmentJobInsertBatchItemDo;
import ${projectDomain}.pojo.dao.system.department.job.SystemDepartmentJobUpdateBatchDo;
import ${projectDomain}.pojo.dao.system.department.job.SystemDepartmentJobUpdateBatchItemDo;
import ${projectDomain}.pojo.dao.system.job.SystemJobDataDo;
import ${projectDomain}.pojo.vo.page.PageVo;
import ${projectDomain}.pojo.vo.system.department.SystemDepartmentCreateVo;
import ${projectDomain}.pojo.vo.system.department.SystemDepartmentDeleteVo;
import ${projectDomain}.pojo.vo.system.department.SystemDepartmentPageVo;
import ${projectDomain}.pojo.vo.system.department.SystemDepartmentTreeVo;
import ${projectDomain}.pojo.vo.system.department.SystemDepartmentUpdateVo;
import ${projectDomain}.pojo.vo.system.department.SystemDepartmentViewVo;
import ${projectDomain}.utils.LoggerUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.ObjectUtils;
import com.unswift.utils.StringUtils;

@Service
@Api(value="部门服务", author="liyunlong", date="2024-01-11", version="1.0.0")
public class SystemDepartmentService extends BaseService{
	
	@Autowired
	@ApiField("部门公共服务")
	private SystemDepartmentAdapter systemDepartmentAdapter;
	
	@Autowired
	@ApiField("职位公共服务")
	private SystemJobAdapter systemJobAdapter;
	
	@Autowired
	@ApiField("部门职位公共服务")
	private SystemDepartmentJobAdapter systemDepartmentJobAdapter;
	
	@Autowired
	@ApiField("用户部门职位公共服务")
	private SystemDepartmentJobUserAdapter systemDepartmentJobUserAdapter;
	
	@ApiMethod(value="查询系统部门树数据", params=@ApiField("树查询对象"), returns=@ApiField("包含查询数据的树对象"))
    public SystemDepartmentTreeVo findTreeList(SystemDepartmentTreeBo searchBo){
        SystemDepartmentSearchDo search=this.convertPojo(searchBo, SystemDepartmentSearchDo.class);
        systemDepartmentAdapter.setFieldToLike(search, "name", ObjectUtils.asList("code_", "name_"));
        systemDepartmentAdapter.addOrderBy(search, "parent_id_", Sql.ORDER_BY_ASC);
        systemDepartmentAdapter.addOrderBy(search, "sort_", Sql.ORDER_BY_ASC);
        SystemDepartmentTreeVo root=new SystemDepartmentTreeVo(-1L, "部门树", true, false);
        root.setIcon(TreeIconEnum.ORGANIZATION.getKey());
        List<SystemDepartmentDataDo> list = systemDepartmentAdapter.findList(search);
        if(ObjectUtils.isNotEmpty(list)) {
        	String spreadPath=null;
        	if(ObjectUtils.isNotEmpty(searchBo.getSpreadId())){
        		SystemDepartmentDataDo spreadDepartment=systemDepartmentAdapter.findById(searchBo.getSpreadId());
        		if(ObjectUtils.isNotEmpty(spreadDepartment)) {
        			spreadPath=spreadDepartment.getParentPath();
        		}
        	}
            Set<Long> ids=list.stream().map(r -> r.getId()).collect(Collectors.toSet());
            systemDepartmentAdapter.findParent(list, ids);
        	List<SystemDepartmentDataDo> rootList=list.stream().filter(r -> r.getType().equals("headOffice") && ObjectUtils.isEmpty(r.getParentId())).collect(Collectors.toList());
        	if(ObjectUtils.isEmpty(rootList)){
        		return root;
        	}
        	if(rootList.size()==1) {
        		root.setId(rootList.get(0).getId());
        		root.setTitle(rootList.get(0).getName());
        		systemDepartmentAdapter.parseDepartmentToTree(list, root, spreadPath);
        	} else {
        		List<SystemDepartmentTreeVo> childList=new ArrayList<SystemDepartmentTreeVo>();
        		SystemDepartmentTreeVo childNode;
        		for (SystemDepartmentDataDo department : rootList) {
        			childNode=new SystemDepartmentTreeVo(department.getId(), department.getName());
        			if(ObjectUtils.isNotEmpty(spreadPath) && StringUtils.contains(spreadPath, department.getId()+"", ".")){
        				childNode.setSpread(true);
        			}
        			childList.add(childNode);
        			systemDepartmentAdapter.parseDepartmentToTree(list, childNode, spreadPath);
				}
        		root.setChildren(childList);
        	}
        }
        return root;
    }
	
	@ApiMethod(value="查询部门分页数据", params=@ApiField("分页对象，包含分页信息及查询条件"), returns=@ApiField("包含查询数据的分页对象"))
	public PageVo<SystemDepartmentPageVo> findPageList(SystemDepartmentPageBo searchBo){
		SystemDepartmentPageDo search=this.convertPojo(searchBo, SystemDepartmentPageDo.class);//将Bo转换为Do
		search.setFirstSize((search.getCurrPage()-1)*search.getPageSize());
		PageVo<SystemDepartmentDataDo> page=systemDepartmentAdapter.findPageList(search);//将Do转换为Vo
		return this.convertPage(page, SystemDepartmentPageVo.class);
	}
	
	@ApiMethod(value="查询部门详情", params=@ApiField("详情业务实体，包含id字段"), returns=@ApiField("部门详情数据"))
	public SystemDepartmentViewVo view(SystemDepartmentViewBo viewBo){
		SystemDepartmentSingleDo search=this.convertPojo(viewBo, SystemDepartmentSingleDo.class);
		SystemDepartmentDataDo single=systemDepartmentAdapter.findSingle(search);
		SystemDepartmentViewVo view = this.convertPojo(single, SystemDepartmentViewVo.class);
		if(ObjectUtils.isNotEmpty(view)) {
			view.setJobList(systemJobAdapter.findCodesByDepartmentCode(view.getCode()));
		}
		return view;//将Do转换为Vo
	}

	@Transactional("systemTransactionManager")
	@OperatorLogger(type = OperatorTypeEnum.CREATE)
	@ApiMethod(value="创建部门", params=@ApiField("创建的业务实体"), returns=@ApiField("创建结果{0：未创建，1：已创建}"))
	public SystemDepartmentCreateVo create(SystemDepartmentCreateBo createBo){
		LoggerUtils.setModule(systemDepartmentAdapter.getModule());//设置日志所属模块
		if(ObjectUtils.isNotEmpty(createBo.getJobList())) {
			createBo.setJobNames(systemJobAdapter.findNamesByCodes(createBo.getJobList()));
		}
		SystemDepartmentInsertDo insert=this.convertPojo(createBo, SystemDepartmentInsertDo.class);//将Bo转换为Do
		insert.setParentPath(systemDepartmentAdapter.getCompletePath(insert.getParentId()));//设置资源path
		systemDepartmentAdapter.setInsertDefault(insert);//设置Default
		int result=systemDepartmentAdapter.save(insert, true);
		if(ObjectUtils.isNotEmpty(createBo.getJobList())) {
			List<SystemDepartmentJobInsertBatchItemDo> batchList=new ArrayList<SystemDepartmentJobInsertBatchItemDo>();
			SystemDepartmentJobInsertBatchItemDo item;
			int sort=1;
			for (String jobCode : createBo.getJobList()) {
				item=new SystemDepartmentJobInsertBatchItemDo();
				item.setDepartmentCode(insert.getCode());
				item.setJobCode(jobCode);
				item.setSort(sort);
				batchList.add(item);
				sort++;
			}
			systemDepartmentJobAdapter.saveBatch(new SystemDepartmentJobInsertBatchDo(batchList), true);//保存部门职位
		}
		LoggerUtils.setId(insert.getId());//创建日志需要设置数据id
		return new SystemDepartmentCreateVo(result);
	}
	
	@Transactional("systemTransactionManager")
	@OperatorLogger(type = OperatorTypeEnum.UPDATE)
	@ApiMethod(value="更新部门", params=@ApiField("更新的业务实体"), returns=@ApiField("更新结果{0：未创建，1：已创建}"))
	public SystemDepartmentUpdateVo update(SystemDepartmentUpdateBo updateBo){
		updateBo.setTypeName(cacheAdapter.findDictionaryKeyByValue("departmentType", updateBo.getType()));
		LoggerUtils.setModule(systemDepartmentAdapter.getModule());//设置日志所属模块
		if(ObjectUtils.isNotEmpty(updateBo.getJobList())) {
			updateBo.setJobNames(systemJobAdapter.findNamesByCodes(updateBo.getJobList()));
		}
		SystemDepartmentDataDo view=systemDepartmentAdapter.findById(updateBo.getId());
		view.setTypeName(cacheAdapter.findDictionaryKeyByValue("departmentType", view.getType()));
		if(ObjectUtils.isNotEmpty(updateBo.getJobList())) {
			updateBo.setJobNames(systemJobAdapter.findNamesByDepartmentCode(view.getCode()));
		}
		LoggerUtils.setOriginalData(view);//设置日志原数据对象
		SystemDepartmentUpdateDo update=this.convertPojo(updateBo, SystemDepartmentUpdateDo.class);//将Bo转换为Do
		int result=systemDepartmentAdapter.update(update, true);
		Map<String, Long> jobCodeMap=systemDepartmentJobAdapter.findJobCodeMapByDepartmentCode(view.getCode());
		if(ObjectUtils.isNotEmpty(updateBo.getJobList())) {
			List<SystemDepartmentJobInsertBatchItemDo> insertList=new ArrayList<SystemDepartmentJobInsertBatchItemDo>();
			SystemDepartmentJobInsertBatchItemDo insertItem;
			List<SystemDepartmentJobUpdateBatchItemDo> updateList=new ArrayList<SystemDepartmentJobUpdateBatchItemDo>();
			SystemDepartmentJobUpdateBatchItemDo updateItem;
			int sort=1;
			for (String jobCode : updateBo.getJobList()) {
				if(jobCodeMap.containsKey(jobCode)) {
					updateItem=new SystemDepartmentJobUpdateBatchItemDo();
					updateItem.setId(jobCodeMap.get(jobCode));
					updateItem.setSort(sort);
					updateList.add(updateItem);
					jobCodeMap.remove(jobCode);//存在职位编码了就删除
				}else {
					insertItem=new SystemDepartmentJobInsertBatchItemDo();
					insertItem.setDepartmentCode(view.getCode());
					insertItem.setJobCode(jobCode);
					insertItem.setSort(sort);
					insertList.add(insertItem);
				}
				sort++;
			}
			if(ObjectUtils.isNotEmpty(insertList)) {
				systemDepartmentJobAdapter.saveBatch(new SystemDepartmentJobInsertBatchDo(insertList), true);//保存部门职位
			}
			if(ObjectUtils.isNotEmpty(updateList)) {
				systemDepartmentJobAdapter.updateBatch(new SystemDepartmentJobUpdateBatchDo(updateList), true);
			}
		}
		if(ObjectUtils.isNotEmpty(jobCodeMap)) {//最后没有在map中没有被剔除的就是需要删除的
			jobCodeMap.forEach((k, v)->{
				SystemJobDataDo job = systemJobAdapter.findByCode(k);
				ExceptionUtils.empty(job, "field.empty", String.format("职位“%s”关联职位信息", k));
				ExceptionUtils.trueException(systemDepartmentJobUserAdapter.existsByDepartmentJobId(v), "exists.association", String.format("部门“%s”，职位“%s”", updateBo.getName(), job.getName()), "用户");//存在用户关联的不允许删除
			});
			List<Long> deleteIdList=new ArrayList<Long>(jobCodeMap.values());
			systemDepartmentJobAdapter.deleteBatch(new SystemDepartmentJobDeleteBatchDo(deleteIdList));
		}
		return new SystemDepartmentUpdateVo(result);
	}
	
	@OperatorLogger(type = OperatorTypeEnum.DELETE)
	@ApiMethod(value="删除部门", params=@ApiField("删除业务实体，包含id字段"), returns=@ApiField("删除结果{0：未创建，1：已创建}"))
	public SystemDepartmentDeleteVo delete(SystemDepartmentDeleteBo deleteBo){
		LoggerUtils.setModule(systemDepartmentAdapter.getModule());//设置日志所属模块
		SystemDepartmentDataDo deleteData=systemDepartmentAdapter.findById(deleteBo.getId());
		ExceptionUtils.empty(deleteData, "delete.object.not.exists", "部门信息");//删除对象必须存在
		ExceptionUtils.trueException(systemDepartmentAdapter.existsChild(deleteBo.getId()), "delete.exists.childs", "部门", "部门");
		SystemDepartmentDeleteDo delete=this.convertPojo(deleteBo, SystemDepartmentDeleteDo.class);//将Bo转换为Do
		int result=systemDepartmentAdapter.delete(delete);
		return new SystemDepartmentDeleteVo(result);
	}
}
